package com.cm.rpa;

import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import com.cm.rpa.beans.Button;
import com.cm.rpa.beans.Point;

/**
 * Windows Api 封装
 *
 * @author LWang 2023.01.28
 * @since 1.0.0
 */
public final class WinApi {

    private WinApi() {

    }

    private static final Robot ROBOT;

    static {
        try {
            ROBOT = new Robot();
        } catch (AWTException e) {
            throw new RuntimeException(e);
        }
    }

    private static final int MINIMUM_DURATION = 100;
    private static final int MINIMUM_SLEEP = 50;

    public static void mouseMove(double x, double y) {
        ROBOT.mouseMove((int) x, (int) y);
    }

    /**
     * 将鼠标指针移动到指定坐标
     *
     * @param x        横轴
     * @param y        纵轴
     * @param duration 延时
     */
    public static void mouseMove(double x, double y, long duration) {
        // 切分坐标
        // 读取当前坐标点
        var currentPoint = currentPoint();
        // 计算移动长宽
        var width = x - currentPoint.x();
        var height = y - currentPoint.y();
        // 每一步移动点
        var points = new ArrayList<Point>();
        var sleepAmount = 0;
        // 最大移动距离（绝对值比较）
        var numSteps = (int) (Math.max(Math.abs(width), Math.abs(height)));
        if (numSteps > 0) {
            // 每一步移动间隔
            sleepAmount = (int) (duration / numSteps);
            if (duration > MINIMUM_DURATION) {
                if (sleepAmount < MINIMUM_DURATION) {
                    numSteps = (int) (duration / MINIMUM_SLEEP);
                    sleepAmount = (int) (duration / numSteps);
                }
                if (numSteps > 0) {
                    // 计算每一步移动点
                    var widthSection = width / numSteps;
                    var heightSection = height / numSteps;
                    for (var i = 0; i < numSteps; i++) {
                        currentPoint = new Point(currentPoint.x() + widthSection, currentPoint.y() + heightSection);
                        points.add(currentPoint);
                    }
                }
            }
        }
        points.add(new Point(x, y));
        for (var p : points) {
            mouseMove(p.x(), p.y());
            ROBOT.delay(sleepAmount);
        }
    }

    /**
     * 按下鼠标按键
     *
     * @param button 按键
     */
    public static void mouseDown(Button button) {
        ROBOT.mousePress(button.getButton());
    }

    /**
     * 抬起鼠标按键
     *
     * @param button 按键
     */
    public static void mouseUp(Button button) {
        ROBOT.mouseRelease(button.getButton());
    }

    /**
     * 鼠标左键点击
     */
    public static void leftClick() {
        mouseDown(Button.LEFT);
        ROBOT.delay(100);
        mouseUp(Button.LEFT);
    }

    /**
     * 获取当前鼠标指定定位
     *
     * @return 当前鼠标定位
     */
    public static Point currentPoint() {
        var pointInfo = MouseInfo.getPointerInfo().getLocation();
        return new Point(pointInfo.getX(), pointInfo.getY());
    }

    /**
     * 拖拽到指定位置
     *
     * @param x        横坐标
     * @param y        纵坐标
     * @param duration 延时
     */
    public static void dragTo(double x, double y, long duration) {
        mouseDown(Button.LEFT);
        ROBOT.delay(100);
        mouseMove(x, y, duration);
        mouseUp(Button.LEFT);
    }

    /**
     * 延时
     *
     * @param delay 延时（毫秒）
     */
    public static void delay(long delay) {
        try {
            TimeUnit.MILLISECONDS.sleep(delay);
        } catch (InterruptedException ignored) {
        }
    }

    public static void enter(){
        ROBOT.keyPress(KeyEvent.VK_ENTER);
        ROBOT.keyRelease(KeyEvent.VK_ENTER);
    }

    public static void main(String[] args) {
        mouseMove(0, 0);
        mouseMove(1000, 1000, 1000);
    }
}
